package br.com.saeng2D.objeto.ponto;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.io.PrintWriter;

import br.com.saeng2D.objeto.AbstratoObjeto;
import br.com.saeng2D.util.Constantes;
import br.com.saeng2D.util.P2D;
import br.com.saeng2D.util.R2D;
import br.com.saeng2D.util.Util;

public class Ponto extends AbstratoObjeto {
	private boolean preenchido = Util.getBoolean("ponto_preenchido");
	private final int lado = Util.getInt("diametro_ponto");
	private final int metade = lado / 2;
	private String tipoPonto;
	private String numero;
	
	public Ponto(int x, int y) {
		super(null, "Ponto", x, y, 0, 0);
		corFundo = Util.getCor("cor_ponto");
	}
	
	public AbstratoObjeto prototipo() {
		Ponto ponto = new Ponto(x, y);
		ponto.setCorPlotado(corPlotado);
		ponto.setCorFundo(corFundo);
		ponto.setNumero(numero);
		ponto.setTipoPonto(tipoPonto);
		return ponto;
	}
	
	private Memento memento;

	private class Memento {
		Color corPlotado;
		Ponto ponto;
		
		Memento(Ponto ponto) {
			this.ponto = ponto;
			this.corPlotado = ponto.getCorPlotado(); 
		}
		
		void restaurar() {
			this.ponto.setCorPlotado(this.corPlotado);
		}
	}
	
	public void criarMemento() {
		if(memento != null) {
			return;
		}
		memento = new Memento(this);
	}
	
	public void restaurarMemento() {
		if(memento != null) {
			memento.restaurar();
			memento = null;
		}
	}
	
	public boolean guardandoMemento() {
		return memento != null;
	}
	
	public Color getCorFundoMemento() {
		return memento.corPlotado;
	}
	
	public boolean ehIgual(AbstratoObjeto objeto) {
		if(objeto instanceof Ponto) {
			Ponto ponto = (Ponto) objeto;
			return x == ponto.x && y == ponto.y;
		}
		return false;
	}

	public boolean ehIgualX(AbstratoObjeto objeto) {
		if(objeto instanceof Ponto) {
			Ponto ponto = (Ponto) objeto;
			return x == ponto.x;
		}
		return false;
	}

	public boolean ehIgualY(AbstratoObjeto objeto) {
		if(objeto instanceof Ponto) {
			Ponto ponto = (Ponto) objeto;
			return y == ponto.y;
		}
		return false;
	}
	
	public boolean yMenorQue(Ponto ponto) {
		return y < ponto.y;
	}

	public boolean xMenorQue(Ponto ponto) {
		return x < ponto.x;
	}
	
	public void desenhar(Graphics2D g2) {
		if(!isVisivel()) {
			return;
		}
		g2.setStroke(AbstratoObjeto.LARGURA_LINHA_ABSTRATO_OBJETO);
		if(numero != null) {
			g2.setColor(Constantes.COR_NUMERO_PONTO);
			g2.drawString(numero, x + 10, y - 10);
		}
		if(plotado && corPlotado != null) {
			g2.setColor(corPlotado);
			g2.fill(new Ellipse2D.Float(x - metade, y - metade, lado, lado));
		} else {
			if (selecionado) {
				g2.setColor(corSelecionado);
			} else {
				g2.setColor(corFundo);
			}
			if(preenchido) {
				g2.fill(new Ellipse2D.Float(x - metade, y - metade, lado, lado));
			} else {
				g2.draw(new Ellipse2D.Float(x - metade, y - metade, lado, lado));
			}
		}
	}

	public int distancia(Ponto ponto) {
		int x = ponto.x - this.x;
		int y = ponto.y - this.y;
		return (int) Math.sqrt(x * x + y * y);
	}
	
	public void salvarXML(String prefixo, PrintWriter pw) {
		pw.print(prefixo + "\t<ponto x='" + x + "' y='" + y + "'/>\r\n");
	}

	public boolean estarSob(int x, int y) {
		return getArea().contem(x, y);
	}

	public R2D getArea() {
		int X = x - metade;
		int Y = y - metade;
		if(X < 0) {
			X = 0;	
		}
		if(Y < 0) {
			Y = 0;	
		}
		return new R2D(X, Y, lado, lado);
	}
	
	public void normalizar() {
		P2D p2d = Util.normalizar(x, y);
		x = p2d.x;
		y = p2d.y;
	}	
	
	public String toString() {
		return "Ponto[x=" + x + ", y=" + y + "]";
	}

	public void alterarTamanho(int tamanho) {
		//TODO implementar
	}

	public boolean isPreenchido() {
		return preenchido;
	}

	public void setPreenchido(boolean preenchido) {
		this.preenchido = preenchido;
	}

	public String getNumero() {
		return numero;
	}

	public void setNumero(String numero) {
		this.numero = numero;
	}

	public String getTipoPonto() {
		return tipoPonto;
	}

	public void setTipoPonto(String tipoPonto) {
		this.tipoPonto = tipoPonto;
	}
}